package com.campuscarbooking.api.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * RabbitMQ操作日志切面
 */
@Aspect
@Component
@Slf4j
public class RabbitMQLoggingAspect {

    /**
     * 定义切点 - RabbitTemplate操作
     */
    @Pointcut("execution(* org.springframework.amqp.rabbit.core.RabbitTemplate.*(..))")
    public void rabbitTemplatePointcut() {
    }

    /**
     * 定义切点 - RabbitMQ消息监听器
     */
    @Pointcut("@annotation(org.springframework.amqp.rabbit.annotation.RabbitListener)")
    public void rabbitListenerPointcut() {
    }

    /**
     * 环绕通知 - 记录RabbitTemplate操作
     */
    @Around("rabbitTemplatePointcut() && args(exchange, routingKey, message, ..)")
    public Object logRabbitTemplateOperation(ProceedingJoinPoint joinPoint, 
                                            String exchange, 
                                            String routingKey, 
                                            Object message) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        
        // 只记录发送消息相关的方法
        if (methodName.contains("send") || methodName.contains("convert")) {
            log.info("发送消息到RabbitMQ, 交换机: {}, 路由键: {}, 消息: {}", 
                    exchange, routingKey, message);
        }
        
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long executionTime = System.currentTimeMillis() - startTime;
        
        if (methodName.contains("send") || methodName.contains("convert")) {
            log.info("消息发送完成, 耗时: {} ms", executionTime);
        }
        
        return result;
    }

    /**
     * 环绕通知 - 记录RabbitMQ消息监听器
     */
    @Around("rabbitListenerPointcut()")
    public Object logRabbitListener(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        
        log.info("接收到RabbitMQ消息, 监听方法: {}, 消息内容: {}", methodName, args);
        
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long executionTime = System.currentTimeMillis() - startTime;
        
        log.info("消息处理完成, 监听方法: {}, 耗时: {} ms", methodName, executionTime);
        
        return result;
    }

    /**
     * 异常通知 - 记录RabbitMQ操作异常
     */
    @AfterThrowing(pointcut = "rabbitTemplatePointcut() || rabbitListenerPointcut()", throwing = "ex")
    public void logRabbitMQException(JoinPoint joinPoint, Throwable ex) {
        String methodName = joinPoint.getSignature().getName();
        log.error("RabbitMQ操作 [{}] 执行异常: {}", methodName, ex.getMessage(), ex);
    }
} 